package zip;

import Util.CreateFileUtil;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.tukaani.xz.LZMA2Options;
import org.tukaani.xz.XZInputStream;
import org.tukaani.xz.XZOutputStream;

import java.io.*;
import java.util.Base64;
import java.util.HashMap;

public class XZTest extends TestParent {
    @Param({"1", "2", "3", "4", "5", "6", "7", "8", "9"})
    public int LEVEL;
    @Param({"1", "2", "3", "4", "5", "6", "7", "8", "9"})
    public int CORE;
    static HashMap<Integer, byte[]> compressFile;
    static HashMap<Integer, byte[]> deCompressFile;

    static {
        compressFile = new HashMap<>();
        deCompressFile = new HashMap<>();
        for (int i = 1; i < 10; i++) {
            compressFile.put(i, CreateFileUtil.getBytesByFile("./test/test_" + i + ".json"));
            deCompressFile.put(i, CreateFileUtil.getBytesByFile("./test/test_" + i + ".XZ_9"));
        }
    }

    @Benchmark
    public byte[] compress() throws IOException {
        byte[] out = Base64.getEncoder().encode(lzma2(compressFile.get(LEVEL), CORE));
        CreateFileUtil.bytes2File(out, "./test/", "test_" + LEVEL + ".XZ_" + CORE);
        return out;
    }

    @Benchmark
    public byte[] deCompress() throws IOException {
        byte[] out = unlzma2(Base64.getDecoder().decode(deCompressFile.get(LEVEL)));
        CreateFileUtil.bytes2File(out, "./test/", "test_" + LEVEL + ".XZ.json");
        return out;
    }


    public static byte[] lzma2(final byte[] inData, final int core) throws IOException {
        ByteArrayOutputStream xzOutput = new ByteArrayOutputStream();
        try (XZOutputStream xzStream = new XZOutputStream(xzOutput, new LZMA2Options(core))) {
            xzStream.write(inData);
        }
        return xzOutput.toByteArray();
    }

    public static byte[] unlzma2(final byte[] compressedStr) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(compressedStr));
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        XZInputStream xzIn = new XZInputStream(in);
        final byte[] buffer = new byte[1024];
        try {
            int n;
            while (-1 != (n = xzIn.read(buffer))) {
                out.write(buffer, 0, n);
            }
        } catch (Exception e) {
            return null;
        } finally {
            in.close();
            out.close();
            xzIn.close();
        }
        return out.toByteArray();
    }
}
